package com.shycloud.mido.music.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.shycloud.mido.common.core.constant.CommonConstants;
import com.shycloud.mido.common.core.util.R;
import com.shycloud.mido.common.security.util.SecurityUtils;
import com.shycloud.mido.member.api.entity.Member;
import com.shycloud.mido.member.api.feign.RemoteMemberService;
import com.shycloud.mido.member.api.util.UUIDUtil;
import com.shycloud.mido.music.domain.MisMusic;
import com.shycloud.mido.music.domain.MisMusicMemberStar;
import com.shycloud.mido.music.mapper.MisMusicMemberStarMapper;
import com.shycloud.mido.music.service.MisMusicMemberStarService;
import com.shycloud.mido.music.service.MisMusicService;
import com.shycloud.mido.music.vo.MusicMemberStarRankVO;
import com.shycloud.mido.music.vo.MusicMemberStarVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;

import java.time.*;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import java.util.concurrent.TimeUnit;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * 练琴排行榜 controller
 *
 * @author nianhua.jiang
 * @date 2021/9/13 13:50
 */
@RestController
@AllArgsConstructor
@RequestMapping("/star")
@Api(tags = "练琴排行榜")
public class MemberMusicStarController {

	/** 排行榜业务 service */
	private final MisMusicMemberStarService starService;
	/** 排行榜业务 mapper */
	private final MisMusicMemberStarMapper starMapper;
	/** 曲目模块 service */
	private final MisMusicService musicService;

	private final RedisTemplate redisTemplate;
	/** 用户模块 feign */
	private final RemoteMemberService memberService;
	/** 0-日榜 */
	private static final String TYPE_DAY_RANK = "0";
	/** 1-周榜 */
	private static final String TYPE_WEEK_RANK = "1";
	/** 2-月榜 */
	private static final String TYPE_MONTH_RANK = "2";

	/**
	 * 记录练琴数据接口
	 *
	 * @param misMusicMemberStar 练琴数据
	 * @return com.shycloud.mido.common.core.util.R
	 * @author nianhua.jiang
	 * @date 2021/9/13 13:55
	 */
	@PostMapping("savePracticeData")
	@ApiOperation("保存练琴数据")
	public R<Boolean> savePracticeData(@RequestBody MusicMemberStarVO misMusicMemberStar) {

		if (StringUtils.isBlank(misMusicMemberStar.getVersion())) {
			return new R<>(CommonConstants.FAIL, "排行榜全新升级，请更新到最新版本", false);
		}

		if (StringUtils.equals(misMusicMemberStar.getVersion(), "2")) {
			return new R<>(CommonConstants.FAIL, "排行榜全新升级，请更新到最新版本", false);
		}

		//设置 2 秒延迟，防止恶意刷星
		Boolean saveStudentRedis = redisTemplate.opsForValue()
				.setIfAbsent("savePracticeData_" + misMusicMemberStar.getMemberId(), "1", 2, TimeUnit.SECONDS);

		if (!saveStudentRedis) {
			return new R<>(true);
		}

		misMusicMemberStar.setCreateTime(LocalDateTime.now());

		Integer fullMarkStar = misMusicMemberStar.getFullMarkStar();
		Integer hardworkingStar = misMusicMemberStar.getHardworkingStar();

		if (fullMarkStar != 0 && hardworkingStar != 0) {
			//保存满分星
			misMusicMemberStar.setHardworkingStar(0);
			misMusicMemberStar.setFullMarkStar(fullMarkStar);
			starService.save(misMusicMemberStar);
			//保存勤奋星
			misMusicMemberStar.setId(UUIDUtil.getUUID32());
			misMusicMemberStar.setHardworkingStar(hardworkingStar);
			misMusicMemberStar.setFullMarkStar(0);
			return new R<>(starService.save(misMusicMemberStar));
		}

		return new R<>(starService.save(misMusicMemberStar));
	}

	/**
	 * 获取某个曲目的用户排行
	 *
	 * @return com.shycloud.mido.common.core.util.R
	 * @author nianhua.jiang
	 * @date 2021/9/14 10:41
	 */
	@GetMapping("getMemberRankByMusicId")
	@ApiOperation("获取某个曲目的用户排行")
	public R<Object> getMemberRankByMusicId(Integer current, Integer size, Integer musicId, String memberId) {

		//新增自己所在排名位置
		Map<String, Object> resMap = new HashMap<>(2);

		Page<MusicMemberStarVO> page = new Page<>(current == null ? 1 : current, size == null ? 10 : size);
		if (SecurityUtils.getMember() != null) {
			memberId = SecurityUtils.getMember().getId();
		}

		IPage<MusicMemberStarVO> rankList = starMapper.getMemberRankByMusicId(page, musicId, memberId);
		MusicMemberStarRankVO myRank = starMapper.getMemberRankByMusicIdMe(musicId, memberId);

		if (myRank == null) {
			myRank = starMapper.getMemberInfo(memberId);
			//未上榜要返回 musicName
			MisMusic music = musicService.getById(musicId);
			myRank.setMusicName(music.getName());
			myRank.setRank(-1);
		}

		//前一名数据 和 后一名数据
		Integer rankBefore = myRank.getRank() - 1;
		Integer rankAfter = myRank.getRank() + 1;

		if (rankAfter + 1 <= 100) {
			resMap.put("beforeAndAfterRank", null);
		} else {
			//rank = 100时，前面两个不统计
			if (myRank.getRank() == 101 || myRank.getRank() == 102) {
				rankBefore = -1;
			}
			List<MusicMemberStarRankVO> beforeAndAfterRank = starMapper
					.getMemberRankByMusicIdByRank(memberId, musicId, rankBefore, rankAfter);
			resMap.put("beforeAndAfterRank", beforeAndAfterRank);
		}

		resMap.put("rankList", rankList);
		resMap.put("myRank", myRank);

		return new R<>(resMap);

	}

	/**
	 * 获取排行榜（周榜，月榜，总榜）
	 *
	 * @param type 1-周榜 2-月榜 3-总榜
	 * @return com.shycloud.mido.common.core.util.R
	 * @author nianhua.jiang
	 * @date 2021/9/14 10:35
	 */
	@GetMapping("getMemberRankHardWorking")
	@ApiOperation("获取排行榜勤奋榜（日榜，周榜，月榜，总榜）")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "current", value = "页数", paramType = "query", dataType = "int"),
			@ApiImplicitParam(name = "type", value = "类型(0-日榜 1-周榜 2-月榜 3-总榜)", paramType = "query", dataType = "String"),
			@ApiImplicitParam(name = "size", value = "每页显示条数", paramType = "query", dataType = "int")
	})
	public R<Object> getMemberRankHardWorking(String type, Integer current, Integer size, String memberId) {

		Map<String, Object> resMap = new HashMap<>(2);

		if (SecurityUtils.getMember() != null) {
			memberId = SecurityUtils.getMember().getId();
		}

		if (current == null || size == null) {
			return new R<>(CommonConstants.FAIL, "current和size必传！", false);
		}

		LocalDate startDate = null;
		LocalDate endDate = null;
		long surplusDays = 0;

		//计算时间段，获取当前时间
		LocalDate date = LocalDate.now();
		//2021-10-19 号新增日榜需求
		if (StringUtils.equals(type, TYPE_DAY_RANK)) {
			startDate = LocalDate.now();
			endDate = LocalDate.now();
		}
		//周榜
		else if (StringUtils.equals(type, TYPE_WEEK_RANK)) {
			int weekValue = date.getDayOfWeek().getValue() - 1;
			//每周开始日期
			startDate = date.plusDays(-1 * weekValue);
			//每周结束日期
			endDate = startDate.plusDays(6);

			surplusDays = endDate.toEpochDay() - LocalDate.now().toEpochDay();
		}
		// 月榜
		else if (StringUtils.equals(type, TYPE_MONTH_RANK)) {
			Month month = date.getMonth();
			//本月有多少天传传递
			int monthValueCount = date.withMonth(month.getValue()).lengthOfMonth();
			//每月开始日期
			startDate = date.with(TemporalAdjusters.firstDayOfMonth());
			//每月结束日期
			endDate = startDate.plusDays(monthValueCount - 1);
			surplusDays = endDate.toEpochDay() - LocalDate.now().toEpochDay();
		}

		IPage<MusicMemberStarRankVO> memberRankHardWorkingPage = starMapper
				.getMemberRankHardWorking(new Page<>(current, size), startDate, endDate, memberId);

		MusicMemberStarRankVO myRank = starMapper
				.getMemberRankHardWorkingMe(startDate, endDate, memberId);

		if (myRank == null) {
			myRank = starMapper.getMemberInfo(memberId);
			myRank.setRank(-1);
		}

		myRank.setStartDate(startDate);
		myRank.setEndDate(endDate);
		myRank.setSurplusDays(surplusDays);

		//前一名数据 和 后一名数据
		Integer rankBefore = myRank.getRank() - 1;
		Integer rankAfter = myRank.getRank() + 1;

		if (rankAfter + 1 <= 100) {
			resMap.put("beforeAndAfterRank", null);
		} else {
			//rank = 100时，前面两个不统计
			if (myRank.getRank() == 101 || myRank.getRank() == 102) {
				rankBefore = -1;
			}
			List<MusicMemberStarRankVO> beforeAndAfterRank = starMapper
					.getMemberRankHardWorkingByRank(memberId, startDate, endDate, rankBefore, rankAfter);
			resMap.put("beforeAndAfterRank", beforeAndAfterRank);
		}

		resMap.put("rankList", memberRankHardWorkingPage);
		resMap.put("myRank", myRank);

		return new R<>(resMap);
	}

	/**
	 * 获取排行榜（周榜，月榜，总榜）
	 *
	 * @param type 1-周榜 2-月榜 3-总榜
	 * @return com.shycloud.mido.common.core.util.Rz
	 * @author nianhua.jiang
	 * @date 2021/9/14 10:35
	 */
	@GetMapping("getMemberRankFullMark")
	@ApiOperation("获取排行榜满分榜（周榜，月榜，总榜）")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "current", value = "页数", paramType = "query", dataType = "int"),
			@ApiImplicitParam(name = "type", value = "类型(1-周榜 2-月榜 3-总榜)", paramType = "query", dataType = "String"),
			@ApiImplicitParam(name = "size", value = "每页显示条数", paramType = "query", dataType = "int")
	})
	public R<Object> getMemberRankFullMark(String type, Integer current, Integer size, String memberId) {

		if (SecurityUtils.getMember() != null) {
			memberId = SecurityUtils.getMember().getId();
		}

		Map<String, Object> resMap = new HashMap<>(2);

		if (current == null || size == null) {
			return new R<>(CommonConstants.FAIL, "current和size必传！", false);
		}

		LocalDate startDate = null;
		LocalDate endDate = null;
		long surplusDays = 0;
		//计算时间段，获取当前时间
		LocalDate date = LocalDate.now();
		if (StringUtils.equals(type, TYPE_DAY_RANK)) {
			startDate = LocalDate.now();
			endDate = LocalDate.now();
		}
		//周榜
		else if (StringUtils.equals(type, TYPE_WEEK_RANK)) {
			int weekValue = date.getDayOfWeek().getValue() - 1;
			//每周开始日期
			startDate = date.plusDays(-1 * weekValue);
			//每周结束日期
			endDate = startDate.plusDays(6);
			surplusDays = endDate.toEpochDay() - LocalDate.now().toEpochDay();
		}
		// 月榜
		else if (StringUtils.equals(type, TYPE_MONTH_RANK)) {
			Month month = date.getMonth();
			//本月有多少天
			int monthValueCount = date.withMonth(month.getValue()).lengthOfMonth();
			//每月开始日期
			startDate = date.with(TemporalAdjusters.firstDayOfMonth());
			//每月结束日期
			endDate = startDate.plusDays(monthValueCount - 1);
			surplusDays = endDate.toEpochDay() - LocalDate.now().toEpochDay();
		}
		IPage<MusicMemberStarRankVO> memberRankFullMarkPage = starMapper
				.getMemberRankFullMark(new Page<MusicMemberStarRankVO>(current, size), startDate, endDate, memberId);

		MusicMemberStarRankVO myRank = starMapper.getMemberRankFullMarkMe(startDate, endDate, memberId);

		if (myRank == null) {
			myRank = starMapper.getMemberInfo(memberId);
			myRank.setRank(-1);
		}
		myRank.setStartDate(startDate);
		myRank.setEndDate(endDate);
		myRank.setSurplusDays(surplusDays);

		//前一名数据 和 后一名数据
		Integer rankBefore = myRank.getRank() - 1;
		Integer rankAfter = myRank.getRank() + 1;

		if (rankAfter + 1 <= 100) {
			resMap.put("beforeAndAfterRank", null);
		} else {
			//rank = 100时，前面两个不统计
			if (myRank.getRank() == 101 || myRank.getRank() == 102) {
				rankBefore = -1;
			}
			List<MusicMemberStarRankVO> beforeAndAfterRank = starMapper
					.getMemberRankFullMarkByRank(memberId, startDate, endDate, rankBefore, rankAfter);
			resMap.put("beforeAndAfterRank", beforeAndAfterRank);
		}

		resMap.put("rankList", memberRankFullMarkPage);
		resMap.put("myRank", myRank);

		return new R<>(resMap);
	}

	@GetMapping("batchStarRank")
	public R<Boolean> batchStarRank() {

		//加锁
		//加入同步锁
		//时间限制防止周榜混乱
		LocalDate date = LocalDate.now();

		//周榜
		int weekValue = date.getDayOfWeek().getValue() - 1;
		//每周开始日期
		LocalDate startDate = date.plusDays(-1 * weekValue);
		//每周结束日期
		LocalDate endDate = startDate.plusDays(6);

		//1.查询所有重复的勤奋星数据，准备整合
		List<MisMusicMemberStar> starS = starMapper.getHardWorkingStarList(startDate, endDate);

		System.out.println("开始整合星星数据 -----> ");

		//返回每一条数据，以ID为主键开始更新操作
		for (MisMusicMemberStar star : starS) {
			starMapper.updateById(star);
			//删除其余没用的数据
			starMapper.delOtherHardWorkingData(
					star.getMusicId(), star.getMemberId(),
					star.getHardworkingStar(),
					startDate, endDate);
		}

		System.out.println("星星整合完成！");

		return new R<>(true);
	}

	@GetMapping("batchMusicStar")
	public R batchMusicStar() {
		List<MisMusicMemberStar> lists = new ArrayList<>();
		for (int i = 0; i < 200; i++) {
			MisMusicMemberStar memberStar = new MisMusicMemberStar();
			memberStar.setFullMarkStar(0);
			memberStar.setHardworkingStar(3);
			memberStar.setMusicId(10874);
			memberStar.setMusicName("003爷爷的大钟");
			memberStar.setScore(100);
			memberStar.setPlayingMode("1");
			memberStar.setCreateTime(LocalDateTime.now());
			lists.add(memberStar);
		}
		return new R(starService.saveBatch(lists));
	}

//	/**
//	 * 排行榜 BUG 批量补偿接口
//	 *
//	 * @author nianhua.jiang
//	 * @date 2021/10/29 10:41
//	 */
//	@GetMapping("batchGiveGold")
//	public R batchGiveGold() {
//
//		List<MisMusicMemberStar> stars = starMapper
//				.selectList(new QueryWrapper<MisMusicMemberStar>().groupBy("member_id"));
//
//		List<Member> members = new ArrayList<>();
//
//		//批量更新
//		for (MisMusicMemberStar star : stars) {
//			Member member = new Member();
//			member.setGold(100);
//			member.setId(star.getMemberId());
//			members.add(member);
//		}
//		return memberService.batchSaveMemberGold(members);
//	}


}
